package com.jsb.controller;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.annotation.SystemControllerLog;
import com.google.common.collect.Maps;
import com.jsb.common.config.Const;
import com.jsb.common.utils.AesUtil;
import com.jsb.common.utils.CookieUtils;
import com.jsb.common.utils.IdGen;
import com.jsb.common.utils.Md5Util;
import com.jsb.common.utils.StringUtils;
import com.jsb.model.Admin;
import com.jsb.model.AdminExample;
import com.jsb.model.AdminExample.Criteria;
import com.jsb.service.AdminService;
import com.jsb.shiro.FormAuthenticationFilter;
import com.jsb.shiro.UserUtils;

@Controller
public class RegisterAndLoginController {

    private static Logger alogger = Logger.getLogger(RegisterAndLoginController.class);
    
    @Autowired
    private AdminService adminService;



    /**
     * 用户登录验证
     * 
     * @param model
     * @param account
     * @param pwd
     * @param request
     * @return status 
     * @throws IOException
     */
//    @RequestMapping("/login")
    public String login(Model model,String account, String pwd, String remember, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String logUri = "";
        if (null != account && null != pwd && !"".equals(account) && !"".equals(pwd)) {
            AdminExample example = new AdminExample();
            Criteria createCriteria = example.createCriteria();
            createCriteria.andAccountEqualTo(account);
            Criteria criteria = createCriteria;
            criteria.andAccountEqualTo(account);
            example.or(criteria);
            List<Admin> admins = adminService.selectByExample(example);
            if (null != admins && admins.size() == 1) {
            	Admin admin = admins.get(0);
                Cookie[] c;
                if ("remember_pwd".equals(pwd)) {
                    c = request.getCookies();
                    if (c != null) {
                        for (int i = 0; i < c.length; i++) {
                            if ("login_pwd".equals(c[i].getName())) {
                                pwd = c[i].getValue();
                            }
                        }
                    }
                    try {
                        pwd = new String(AesUtil.decrypt(AesUtil.parseHexStr2Byte(pwd), Const.KEY));
                    } catch (Exception e) {
                        for (int i = 0; i < c.length; i++) {
                            Cookie cookie = c[i];
                            if (cookie.getName().equals("login_pwd")) {
                                cookie.setMaxAge(0);
                                response.addCookie(cookie);
                                break;
                            }
                        }
                        model.addAttribute("title", "登录失败");
                        model.addAttribute("info", "账号或密码错误！");
                        model.addAttribute("imgurl", "fail.png");
                        model.addAttribute("url", logUri);
                        model.addAttribute("button", "重新登录");
                        model.addAttribute("isExist", "true");
                        return "/Register/message";
                    }
                }
                if (admin.getPassword().equals(Md5Util.Md5(pwd)) || Md5Util.Md5(admin.getPassword()).equals(Md5Util.Md5(pwd))) {
                	request.getSession().setAttribute("loginUser", admin);
                	  if ("true".equals(remember)) {
                          Cookie cookie = new Cookie("back_login_name", account);
                          cookie.setMaxAge(60 * 60 * 24 * 7);
                          response.addCookie(cookie);
                          Cookie cookie1 = new Cookie("back_login_pwd", AesUtil.parseByte2HexStr(AesUtil.encrypt(admin.getPassword(), Const.KEY)));
                          cookie1.setMaxAge(60 * 60 * 24 * 7);
                          response.addCookie(cookie1);
                      } else {
                          Cookie cookies[] = request.getCookies();
                          Cookie cookie = null;
                          for (int i = 0; i < cookies.length; i++) {
                              cookie = cookies[i];
                              if (cookie.getName().equals("back_login_name")) {
                                  cookie.setMaxAge(0);
                                  response.addCookie(cookie);
                                  continue;
                              }
                              if (cookie.getName().equals("back_login_pwd")) {
                                  cookie.setMaxAge(0);
                                  response.addCookie(cookie);
                                  continue;
                              }
                          }
                          // Cookie cookie = new Cookie("login_name", "");
                          // cookie.setMaxAge(60 * 60 * 24 * 7);
                          // response.addCookie(cookie);
                          // Cookie cookie1 = new Cookie("login_pwd","");
                          // cookie1.setMaxAge(0);
                          // response.addCookie(cookie1);
                      }
                	   String uri = (String) request.getSession().getAttribute("pageuri");
                       if (null != uri) {
                           request.getSession().removeAttribute("pageuri");
                           return "redirect:" + uri;
                       }
                       return "redirect:/main.do?";
                } else {// 密码错误

                }

            } else {// 用户名为不存在 或者数量大于1

            }
        } else {// 密码为空

        }

        model.addAttribute("title", "登录失败");
        model.addAttribute("info", "账号或密码错误！");
        model.addAttribute("imgurl", "fail.png");
        model.addAttribute("url", logUri);
        model.addAttribute("button", "重新登录");
        return "/Register/message";
    }

    /** 
     * 实际的登录代码 
     * 如果登录成功，跳转至首页；登录失败，则将失败信息反馈对用户 
     *  
     * @param request 
     * @param model 
     * @return 
     */  
    @RequestMapping(value = "/login" , method = RequestMethod.POST)  
    @SystemControllerLog(description = "后台登录")
    public String doLogin( Model model,HttpServletRequest request,String account, String pwd,String captcha, String remember) {  
        String msg = "";  
        if(StringUtils.isEmpty(account) || StringUtils.isEmpty(pwd)){
        	return "/";
        }
//        UsernamePasswordToken token = new UsernamePasswordToken(account, pwd);  
        com.jsb.shiro.UsernamePasswordToken token = new com.jsb.shiro.UsernamePasswordToken(account, pwd.toCharArray(), false, null, captcha);
        token.setRememberMe(true);  
        Subject subject = SecurityUtils.getSubject();  
        try {  
            subject.login(token);  
            if (subject.isAuthenticated()) {
            	getSession().setAttribute(subject.getPrincipal(),subject);
            	// 登录成功后，验证码计算器清零
//        		isValidateCodeLogin(account, false, true);
                return "redirect:/main";  
            } else {  
                return "/";  
            }  
        } catch (IncorrectCredentialsException e) {  
            msg = "登录密码错误. Password for account " + token.getPrincipal() + " was incorrect.";  
            model.addAttribute("message", msg);  
        } catch (ExcessiveAttemptsException e) {  
            msg = "登录失败次数过多";  
            model.addAttribute("message", msg);  
        } catch (LockedAccountException e) {  
            msg = "帐号已被锁定. The account for username " + token.getPrincipal() + " was locked.";  
            model.addAttribute("message", msg);  
        } catch (DisabledAccountException e) {  
            msg = "帐号已被禁用. The account for username " + token.getPrincipal() + " was disabled.";  
            model.addAttribute("message", msg);  
        } catch (ExpiredCredentialsException e) {  
            msg = "帐号已过期. the account for username " + token.getPrincipal() + "  was expired.";  
            model.addAttribute("message", msg);  
        } catch (UnknownAccountException e) {  
            msg = "帐号不存在. There is no user with username of " + token.getPrincipal();  
            model.addAttribute("message", msg);  
        } catch (UnauthorizedException e) {  
            msg = "您没有得到相应的授权！" + e.getMessage();  
            model.addAttribute("message", msg);  
        }finally{
        	// 非授权异常，登录失败，验证码加1。
        	String exception = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
    		if (!UnauthorizedException.class.getName().equals(exception)){
//    			model.addAttribute("isValidateCodeLogin", isValidateCodeLogin(account, true, false));
    		}
    		
    		// 验证失败清空验证码
    		request.getSession().setAttribute(ValidateCodeServlet.VALIDATE_CODE, IdGen.uuid());
        }
        return "login";  
    }  
    
    @RequestMapping("/main")
    public String main(Model model, HttpServletRequest request,HttpServletResponse response) {
//    	Admin admin = (Admin) request.getSession().getAttribute("loginUser");
//    	Admin admin = UserUtils.getUser();
//    	Admin admin = (Admin)getSession().getAttribute("loginUser");
    	 Subject subject = SecurityUtils.getSubject();
    	 Subject admin = (Subject) getSession().getAttribute(subject.getPrincipal());
        if (null == admin) {
//        	CookieUtils.setCookie(response, "LOGINED", "false");
            return "redirect:/";
        }
        model.addAttribute("loginUser", admin);
//        CookieUtils.setCookie(response, "LOGINED", "true");
        return "/main";
    }
    
    private Session getSession() {
		Subject currentUser = SecurityUtils.getSubject();
		if (null != currentUser) {
			Session session = currentUser.getSession();
			if (null != session) {
				alogger.info("getsession id:"+session.getId());
				return session;
			}
		}
		return null;
	}
    
    
    private void setSession(Object key, Object value) {
		Subject currentUser = SecurityUtils.getSubject();
		if (null != currentUser) {
			Session session = currentUser.getSession();
			if (null != session) {
				session.setAttribute(key, value);
			}
		}
	}
    
    /**
	 * 是否是验证码登录
	 * @param useruame 用户名
	 * @param isFail 计数加1
	 * @param clean 计数清零
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static boolean isValidateCodeLogin(String useruame, boolean isFail, boolean clean){
		Session session = UserUtils.getSession();
		Map<String, Integer> loginFailMap = (Map<String, Integer>)session.getAttribute("loginFailMap");
		if (loginFailMap==null){
			loginFailMap = Maps.newHashMap();
			session.setAttribute("loginFailMap", loginFailMap);
		}
		Integer loginFailNum = loginFailMap.get(useruame);
		if (loginFailNum==null){
			loginFailNum = 0;
		}
		if (isFail){
			loginFailNum++;
			loginFailMap.put(useruame, loginFailNum);
		}
		if (clean){
			loginFailMap.remove(useruame);
		}
		return loginFailNum >= 3;
	}

    /**
     * 
     * @param info
     * @param response
     */
    private void write(String info, HttpServletResponse response) {
        try {
            response.getWriter().write(info);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    @RequestMapping("/checkPwd")
    @RequiresAuthentication
    public void checkPwd(HttpServletRequest request,HttpServletResponse response,@RequestParam(value = "param")String pwd){
//    	HttpSession session = request.getSession();
//    	Admin admin = (Admin) session.getAttribute("loginUser");
    	 Subject subject = SecurityUtils.getSubject();
    	 Subject admin = (Subject) getSession().getAttribute(subject.getPrincipal());
    	if(!admin.isAuthenticated()){
    		write("{\"info\":\"登录超时，重新登录！\",\"status\":\"n\"}", response);
    	}else{
    		if(StringUtils.isEmpty(pwd)){
        		write("{\"info\":\"原密码错误！\",\"status\":\"n\"}", response);
    		}else{
    			AdminExample example = new AdminExample();
    			Criteria createCriteria = example.createCriteria();
    			createCriteria.andAccountEqualTo(subject.getPrincipal().toString());
				List<Admin> selectByExample = adminService.selectByExample(example );
				String password = "";
				if(null != selectByExample && selectByExample.size()>0){
					password = selectByExample.get(0).getPassword();
				}
				if(Md5Util.checkPassword(pwd, password)){
            		write("{\"info\":\"通过信息验证！\",\"status\":\"y\"}", response);
    			}else{
            		write("{\"info\":\"原密码错误！\",\"status\":\"n\"}", response);
    			}
    		}  	
    	}
    	
    }
    @RequestMapping("/toUpdatePwd")
    @RequiresAuthentication
    public String toUpdatePwd(HttpServletRequest request){
    	HttpSession session = request.getSession();
    	String currentTimeMillis = String.valueOf(System.currentTimeMillis());
		session.setAttribute("checkPwdToken", currentTimeMillis);
    	return "/Register/updatepwd";
    }
    
    @RequestMapping("/updatePwd")
    @RequiresAuthentication
    public String updatePwd(Model model,HttpServletRequest request,String checkPwdToken,String pwd1){
    	HttpSession session = request.getSession();
    	String attr = (String) session.getAttribute("checkPwdToken");
    	if(StringUtils.isNotEmpty(checkPwdToken)&&checkPwdToken.equals(attr)){
//    		Admin admin1 = (Admin)session.getAttribute("loginUser");
    		Subject subject = SecurityUtils.getSubject();
    		AdminExample example = new AdminExample();
			Criteria createCriteria = example.createCriteria();
			createCriteria.andAccountEqualTo(subject.getPrincipal().toString());
			List<Admin> selectByExample = adminService.selectByExample(example );
			if(null != selectByExample){
				Admin admin1 = selectByExample.get(0);
				String id = admin1.getId();
				Admin admin = new Admin();
				admin.setId(id);
				admin.setPassword(Md5Util.Md5(pwd1));
				adminService.updateAdmin(admin);
				subject.logout();
				model.addAttribute("imgurl", "wc.png");
				model.addAttribute("url", "");
				model.addAttribute("info", "密码修改成功请重新登录");
				model.addAttribute("button", "重新登录");
				return "/Register/message";
			}else{
				model.addAttribute("imgurl", "fail.png");
	    		model.addAttribute("url", "toUpdatePwd");
	    		model.addAttribute("info", "修改密码出现错误请重新修改");
	    		model.addAttribute("button", "修改密码");
	    		return "/Register/message";
			}
    	}else{
    		model.addAttribute("imgurl", "fail.png");
    		model.addAttribute("url", "toUpdatePwd");
    		model.addAttribute("info", "修改密码出现错误请重新修改");
    		model.addAttribute("button", "修改密码");
    		return "/Register/message";
    	}
    }

}
